<?php

require_once 'FCatalogue.class.php';
require_once 'postgresql/FPostgresConnection.class.php';
require_once 'postgresql/FPostgresCatalogue.class.php';
require_once 'mysql/FMySQLConnection.class.php';
require_once 'mysql/FMySQLCatalogue.class.php';

class FDatabase
{
 
    private $database;
    private $catalogue;
    private $sql;
    private $start;
    private $limit;
    private $total;
    
    private $error;
    
    public function __construct($dbName = 'system')
    {
        $xml = new FXMLEditor();

        $schema = $xml->getValue("db.$dbName.schema");
        $user = $xml->getValue("db.$dbName.user");
        $password = $xml->getValue("db.$dbName.password");
        $host = $xml->getValue("db.$dbName.host");
        $port = $xml->getValue("db.$dbName.port");

        // Construir o objeto de interface ao banco de dados, conforme definido no arquivo de configuração.
        if ( strtolower($xml->getValue("db.$dbName.sgdb")) == 'postgres' || strtolower($xml->getValue("db.$dbName.sgdb")) == 'postgresql' || strtolower($xml->getValue("db.$dbName.sgdb")) == 'psql' )
        {
            $this->database = new FPostgresConnection($schema, $user, $password, $host, $port);
            $this->catalogue = new FPostgresCatalogue($this->database);
        }
        
        if ( strtolower($xml->getValue("db.$dbName.sgdb")) == 'mysql' )
        {
            $this->database = new FMySQLConnection($schema, $user, $password, $host, $port);
            $this->catalogue = new FMySQLCatalogue($this->database);
        }
        
        // TODO: Implementar objetos para interface com Sqlite, Firebird...
    }
    
    /**
     * Método para gerar um id para um novo registro na tabela $table.
     * @author Bruno Edgar Fuhr [brunofuhr@yahoo.com.br]
     * @since 29/03/2011
     * 
     * @param $table - Tabela em que se deseja criar o novo id.
     * @param $field - Campo que é chave primária da tabela. Default 'codigo'.
     */
    public function getIdForTable($table, $field = 'codigo')
    {
        return $this->catalogue->getIdForTable($table, $field);
    }
    
    /**
     * Listar os nomes das colunas de uma tabela.
     * TODO: considerar esquema.
     * 
     * @param string $table Nome da tabela.
     * @return array Vetor com a listagem de colunas da tabela
     */
    public function getTableColumns($table)
    {
        return $this->catalogue->getTableColumns($table);
    }
    
    /**
     * Listar as informações de uma coluna da tabela.
     * 
     * @param String $table
     * @param String $column
     * @return Array
     */
    public function getColumnInfo($table, $column)
    {
        return $this->catalogue->getColumnInfo($table, $column);
    }
    
    /**
     * Obtém as chaves primárias da tabela.
     * 
     * @param String $table - Nome da tabela
     * @return Array com os nomes e tipos das chaves primárias.
     */
    public function getTablePrimaryKey($table)
    {
        return $this->catalogue->getTablePrimaryKey($table);
    }
    
    public function getTableForeignKeys($table)
    {
        return $this->catalogue->getTableForeignKeys($table);
    }
    
    public function getForeignTables($table)
    {
        return $this->catalogue->getForeignTables($table);
    }

    /**
     * Método para executar a função query do objeto de conexão ao banco
     * @author Bruno Edgar Fuhr [brunofuhr@yahoo.com.br]
     * @since 02/12/2011
     * 
     * @param String $sql - Consulta sql.
     * @return Array - Resultado da consulta. 
     */
    public function query($sql)
    {
        if ( strlen($this->limit) > 0 )
        {
            $total = $this->database->query("SELECT count(*) FROM ($sql) AS sql_count");
            $this->total = $total[0]['count'];
            
            $sql .= " LIMIT {$this->limit} ";
            
            if ( strlen($this->start) > 0 )
            {
                $sql .= " OFFSET {$this->start} ";
            }
            
            $result = $this->database->query($sql);
        }
        else
        {
            $result = $this->database->query($sql);
            $this->total = count($result);
        }
        
        if ( !$result )
        {
            $this->error = $this->database->getError();
        }
        else
        {
            $this->sql = $sql;
        }
        
        return $result;
    }
    
    /**
     * Método para executar a função execute do objeto de conexão ao banco
     * @author Bruno Edgar Fuhr [brunofuhr@yahoo.com.br]
     * @since 02/12/2011
     * 
     * @param String $sql - Comando sql.
     * @return boolean - Retorna true em caso de sucesso da operação.
     */
    public function execute($sql)
    {
        $this->sql = $sql;
        
        $result = $this->database->execute($this->sql);
        
        if ( !$result )
        {
            $this->error = $this->database->getError();
        }
        
        return $result;
    }
    
    public function getError() {
        return $this->error;
    }

    public function setError($error) {
        $this->error = $error;
    }
    
    public function getSql() {
        return $this->sql;
    }

    public function setSql($sql) {
        $this->sql = $sql;
    }

    public function getStart() {
        return $this->start;
    }

    public function setStart($start) {
        $this->start = $start;
    }

    public function getLimit() {
        return $this->limit;
    }

    public function setLimit($limit) {
        $this->limit = $limit;
    }

    public function getTotal() {
        return $this->total;
    }

    public function setTotal($total) {
        $this->total = $total;
    }
    
}

?>
